跳到主要内容

Go 的全局退出监听

经常会有全局监听退出信号的需求,例如编写的 HTTP 服务或者 gRPC 服务需要监听退出信号时就可以使用这个方式

// signal.go
package util

import (
"log"
"os"
"os/signal"
"syscall"
)

// RegisterExitHandlers is used to register exit handlers
func RegisterExitHandlers(cancelFunc func()) (stop chan struct{}) {
var exitSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} // SIGTERM is POSIX specific

stop = make(chan struct{})
s := make(chan os.Signal, len(exitSignals))
signal.Notify(s, exitSignals...)

go func() {
// Wait for a signal from the OS before dispatching
// a stop signal to all other goroutines observing this channel.
<-s
log.Println("exit signal received")
if cancelFunc != nil {
cancelFunc()
}
close(stop)
}()

return stop
}

使用的时候也很简单

package main

import (
"context"
"log"
"stgo/util"
)

func main() {
log.Println("Starting...")
_, cancel := context.WithCancel(context.Background())
stop := util.RegisterExitHandlers(cancel)
defer cancel()

// here is something server.

<-stop
log.Panicln("Goodbye")
}

这样就能监听 ctrl + c 的退出信号了